package com.labot.webapp.action;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.security.core.context.SecurityContextHolder;

import com.labot.Constants;
import com.labot.authentication.ldap.activedirectory.DomainController;
import com.labot.dao.AuditDao;
import com.labot.dao.MailTemplateDao;
import com.labot.model.ClasificacionMuestra;
import com.labot.model.User;
import com.labot.service.AreaManager;
import com.labot.service.CentroManager;
import com.labot.service.ClasificacionMuestraManager;
import com.labot.service.ConfigManager;
import com.labot.service.Dbi18nManager;
import com.labot.service.EnvioManager;
import com.labot.service.MailEngine;
import com.labot.service.PedidoNoConformeManager;
import com.labot.service.RoleManager;
import com.labot.service.ServiceFacturas;
import com.labot.service.ServicePremios;
import com.labot.service.UserManager;
import com.labot.types.AuditEventType;
import com.labot.types.AuditType;
import com.opensymphony.xwork2.ActionSupport;


/**
 * Implementation of <strong>ActionSupport</strong> that contains
 * convenience methods for subclasses.  For example, getting the current
 * user and saving messages/errors. This class is intended to
 * be a base class for all Action classes.
 *
 * @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
 */
public class BaseAction extends ActionSupport {
    private static final long serialVersionUID = 3525445612504421307L;

    /**
     * Constant for cancel result String
     */
    public static final String CANCEL = "cancel";

    /**
     * Transient log to prevent session synchronization issues - children can use instance for logging.
     */
    protected final transient Log log = LogFactory.getLog(getClass());

    protected AuditDao auditDao;

    /**
     * The UserManager
     */
    protected UserManager userManager;
    
    /**
     * The DomainControllerManager
     */
    protected DomainController domainController;
    
    /**
     * The ConfigManager
     */
    protected ConfigManager configManager;

    /**
     * The ConfigManager
     */
    protected Dbi18nManager i18nManager;
    
    protected MailTemplateDao mailTemplateDao;
    
    /**
     * The RoleManager
     */
    protected RoleManager roleManager;
    /**
     * The EnvioManager
     */
    protected EnvioManager envioManager;
    
    protected CentroManager centroManager;
    
    protected AreaManager areaManager;
    
    protected PedidoNoConformeManager pedidonoconformeManager;
    
    protected ClasificacionMuestraManager clasificacionManager;
    
    protected ServicePremios servicePremios;
    
    protected ServiceFacturas serviceFacturas;
    
  
    
    
    public ServiceFacturas getServiceFacturas() {
		return serviceFacturas;
	}

	public void setServiceFacturas(ServiceFacturas serviceFacturas) {
		this.serviceFacturas = serviceFacturas;
	}

	public ServicePremios getServicePremios() {
		return servicePremios;
	}

	public void setServicePremios(ServicePremios servicePremios) {
		this.servicePremios = servicePremios;
	}

	/**
     * Indicator if the user clicked cancel
     */
    protected String cancel;

    /**
     * Indicator for the page the user came from.
     */
    protected String from;

    /**
     * Set to "delete" when a "delete" request parameter is passed in
     */
    protected String delete;

    /**
     * Set to "save" when a "save" request parameter is passed in
     */
    protected String save;

    /**
     * MailEngine for sending e-mail
     */
    protected MailEngine mailEngine;

    /**
     * A message pre-populated with default data
     */
    protected SimpleMailMessage mailMessage;

    /**
     * Velocity template to use for e-mailing
     */
    protected String templateName;

    /**
     * Simple method that returns "cancel" result
     *
     * @return "cancel"
     */
    public String cancel() {
        return CANCEL;
    }

    /**
     * Save the message in the session, appending if messages already exist
     *
     * @param msg the message to put in the session
     */
    @SuppressWarnings("unchecked")
    protected void saveMessage(String msg) {
    	if (msg != null) {
    		if (msg.toLowerCase().contains("developer")) {
    			saveWarningMessage(msg);
    			return;
    		}
    	}
        List messages = (List) getRequest().getSession().getAttribute("messages");
        if (messages == null) {
            messages = new ArrayList();
        }
        messages.add(msg);
        getRequest().getSession().setAttribute("messages", messages);
    }
    
    /**
     * 
     * @param msg
     */
    @SuppressWarnings("unchecked")
    protected void saveExceptionMessage(String msg) {
    	if (msg == null) {
    		return;
    	}
    	String username = "Anonymous";
    	try {
    		username = ((User)SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
    	} catch (Exception e) {
    		//nada....
    	}
    	String refered = null;
    	try{    		
    		refered = ServletActionContext.getRequest().getServletPath();
    	} catch (Exception e) {
    		//nada...
    	}
    	auditDao.log(AuditEventType.ACTION_STRUTS, AuditType.EXCEPTION_ERROR, refered, username, msg);
    	
    	List exceptions = (List) getRequest().getSession().getAttribute("exceptions");
        if (exceptions == null) {
        	exceptions = new ArrayList();
        }
        
        if (msg.length() > 1001) {
        	msg = msg.substring(0, 1000);
        }
        
        exceptions.add(msg);
        getRequest().getSession().setAttribute("exceptions", exceptions);
    }
    
    @SuppressWarnings("unchecked")
    protected void saveErrorMessage(String msg) {
    	String username = "Anonymous";
    	try {
    		username = ((User)SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
    	} catch (Exception e) {
    		//nada....
    	}
    	String refered = null;
    	try{    		
    		refered = ServletActionContext.getRequest().getServletPath();
    	} catch (Exception e) {
    		//nada...
    	}
    	auditDao.log(AuditEventType.ACTION_STRUTS, AuditType.ERROR, refered, username, msg);
    	
    	List errorMessages = (List) getRequest().getSession().getAttribute("errormessages");
        if (errorMessages == null) {
        	errorMessages = new ArrayList();
        }
        errorMessages.add(msg);
        getRequest().getSession().setAttribute("errormessages", errorMessages);
    }
    
    @SuppressWarnings("unchecked")
    protected void saveWarningMessage(String msg) {
    	List warningmessages = (List) getRequest().getSession().getAttribute("warningmessages");
        if (warningmessages == null) {
        	warningmessages = new ArrayList();
        }
        String username = "Anonymous";
    	try {
    		username = ((User)SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
    	} catch (Exception e) {
    		//nada....
    	}
    	String refered = null;
    	try{    		
    		refered = ServletActionContext.getRequest().getServletPath();
    	} catch (Exception e) {
    		//nada...
    	}
    	auditDao.log(AuditEventType.ACTION_STRUTS, AuditType.WARNING, refered, username, msg);
    	
        warningmessages.add(msg);
        getRequest().getSession().setAttribute("warningmessages", warningmessages);
    }
    
    protected void log(AuditType auditType, String msg) {
    	String username = "Anonymous";
    	try {
    		username = ((User)SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
    	} catch (Exception e) {
    		//nada....
    	}
    	String refered = null;
    	try{    		
    		refered = ServletActionContext.getRequest().getServletPath();
    	} catch (Exception e) {
    		//nada...
    	}
    	auditDao.log(AuditEventType.ACTION_STRUTS, auditType, refered, username, msg);
    }
    
    @Override
    public void addActionError(String anErrorMessage) {
    	saveErrorMessage(anErrorMessage);
    }
    
    @Override
    public void addActionMessage(String aMessage) {
    	saveMessage(aMessage);
    }
    
    public void addActionException(String aMessage) {
    	saveExceptionMessage(aMessage);
    }
    
    public void addActionWarning(String aMessage) {
    	saveWarningMessage(aMessage);
    }
    
    public boolean hasActionException() {
    	List exceptions = (List) getRequest().getSession().getAttribute("exceptions");
    	if (exceptions == null) {
        	return false;
        } else if (exceptions.isEmpty()) {
        	return false;
        }
    	return true;
    }
    
    public boolean hasActionWarnings() {
    	List warningss = (List) getRequest().getSession().getAttribute("warningmessages");
    	if (warningss == null) {
        	return false;
        } else if (warningss.isEmpty()) {
        	return false;
        }
    	return true;
    }
    
    @Override
    public boolean hasActionErrors() {
    	if (super.hasActionErrors()) {
    		return true;
    	} else {
    		List errorMessages = (List) getRequest().getSession().getAttribute("errormessages");
    		if (errorMessages == null) {
            	return false;
            } else if (errorMessages.isEmpty()) {
            	return false;
            }
    	}
    	return true;
    }
    
    @Override
    public boolean hasActionMessages() {
    	if (super.hasActionMessages()) {
    		return true;
    	} else {
    		List msgs = (List) getRequest().getSession().getAttribute("messages");
    		if (msgs == null) {
            	return false;
            } else if (msgs.isEmpty()) {
            	return false;
            }
    	}
    	return true;
    }

    @Override
    public Collection<String> getActionErrors() {
    	List errorMessages = (List) getRequest().getSession().getAttribute("errormessages");
        if (errorMessages == null) {
        	return null;
        }
    	Collection<String> result = new ArrayList<String>();
        for (Object o : errorMessages) {
			result.add(o.toString());
		}
        if (super.getActionErrors() != null) {        	
        	result.addAll(super.getActionErrors());
        }
        return result;
    }
    
    
    @Override
    public Collection<String> getActionMessages() {
    	List msgs = (List) getRequest().getSession().getAttribute("messages");
        if (msgs == null) {
        	return super.getActionErrors();
        }
    	Collection<String> result = new ArrayList<String>();
        for (Object o : msgs) {
			result.add(o.toString());
		}
        
        return result;
    }
    
    public Collection<String> getActionExceptions() {
    	List msgs = (List) getRequest().getSession().getAttribute("exceptions");
        if (msgs == null) {
        	return null;
        }
    	Collection<String> result = new ArrayList<String>();
        for (Object o : msgs) {
			result.add(o.toString());
		}
        return result;
    }
    
    public Collection<String> getActionWarnings() {
    	List msgs = (List) getRequest().getSession().getAttribute("warningmessages");
        if ((msgs == null) && (super.getActionErrors() == null)) {
        	return null;
        } else if ((msgs == null) && (super.getActionErrors() != null)) {
        	if (super.getActionErrors().isEmpty()) {
        		return null;
        	} else {
        		return super.getActionErrors();
        	}
        }
    	Collection<String> result = new ArrayList<String>();
        for (Object o : msgs) {
			result.add(o.toString());
		}
        if (super.getActionErrors() != null) {        	
        	result.addAll(super.getActionMessages());
        }
        return result;
    }
    
    
    /**
     * Convenience method to get the Configuration HashMap
     * from the servlet context.
     *
     * @return the user's populated form from the session
     */
    protected Map getConfiguration() {
        Map config = (HashMap) getSession().getServletContext().getAttribute(Constants.CONFIG);
        // so unit tests don't puke when nothing's been set
        if (config == null) {
            return new HashMap();
        }
        return config;
    }

    /**
     * Convenience method to get the request
     *
     * @return current request
     */
    protected HttpServletRequest getRequest() {
        return ServletActionContext.getRequest();
    }

    /**
     * Convenience method to get the response
     *
     * @return current response
     */
    protected HttpServletResponse getResponse() {
        return ServletActionContext.getResponse();
    }

    /**
     * Convenience method to get the session. This will create a session if one doesn't exist.
     *
     * @return the session from the request (request.getSession()).
     */
    protected HttpSession getSession() {
        return getRequest().getSession();
    }

    /**
     * Convenience method to send e-mail to users
     *
     * @param user the user to send to
     * @param msg the message to send
     * @param url the URL to the application (or where ever you'd like to send them)
     */
    protected void sendUserMessage(User user, String msg, String url) {
        if (log.isDebugEnabled()) {
            log.debug("sending e-mail to user [" + user.getEmail() + "]...");
        }

        mailMessage.setTo(user.getFullName() + "<" + user.getEmail() + ">");

        Map<String, Object> model = new HashMap<String, Object>();
        model.put("user", user);
        // TODO: figure out how to get bundle specified in struts.xml
        // model.put("bundle", getTexts());
        model.put("message", msg);
        model.put("applicationURL", url);
        mailEngine.sendMessage(mailMessage, templateName, model);
    }

    public void setUserManager(UserManager userManager) {
        this.userManager = userManager;
    }

    public void setRoleManager(RoleManager roleManager) {
        this.roleManager = roleManager;
    }

    public void setMailEngine(MailEngine mailEngine) {
        this.mailEngine = mailEngine;
    }

    public void setMailMessage(SimpleMailMessage mailMessage) {
        this.mailMessage = mailMessage;
    }

    public void setTemplateName(String templateName) {
        this.templateName = templateName;
    }
    

    public void setConfigManager(ConfigManager configManager) {
		this.configManager = configManager;
	}
    
    public void setI18nManager(Dbi18nManager manager) {
		this.i18nManager = manager;
	}
    
    
    public void setAuditDao(AuditDao auditDao) {
		this.auditDao = auditDao;
	}

	public void setDomainController(DomainController domainController) {
    	this.domainController = domainController;
    }

	/**
     * Convenience method for setting a "from" parameter to indicate the previous page.
     *
     * @param from indicator for the originating page
     */
    public void setFrom(String from) {
        this.from = from;
    }

    public void setDelete(String delete) {
        this.delete = delete;
    }

    public void setSave(String save) {
        this.save = save;
    }
    
    public void setMailTemplateDao(MailTemplateDao mailTemplateDao) {
		this.mailTemplateDao = mailTemplateDao;
	}
    
    protected User getUserLogedin() {
    	return (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    }

	public EnvioManager getEnvioManager() {
		return envioManager;
	}

	public void setEnvioManager(EnvioManager envioManager) {
		this.envioManager = envioManager;
	}

	public CentroManager getCentroManager() {
		return centroManager;
	}

	public void setCentroManager(CentroManager centroManager) {
		this.centroManager = centroManager;
	}

	public AreaManager getAreaManager() {
		return areaManager;
	}

	public void setAreaManager(AreaManager areaManager) {
		this.areaManager = areaManager;
	}
	
	

	public PedidoNoConformeManager getPedidonoconformeManager() {
		return pedidonoconformeManager;
	}

	public void setPedidonoconformeManager(
			PedidoNoConformeManager pedidonoconformeManager) {
		this.pedidonoconformeManager = pedidonoconformeManager;
	}

	public ClasificacionMuestraManager getClasificacionManager() {
		return clasificacionManager;
	}

	public void setClasificacionManager(
			ClasificacionMuestraManager clasificacionManager) {
		this.clasificacionManager = clasificacionManager;
	}

	
    
	
	
    
    
    
}
